﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;

using JavaSubstitutes;

namespace Sprites
{
	public class Sprite
	{
		public static SpriteContext spriteContext;        
		public int xPic, yPic;
		public int wPic = 32;
		public int hPic = 32;
		public int xPicO, yPicO;
		public bool xFlipPic = false; //todo: take private
		public bool yFlipPic = false;
		public Image[,] sheet;
		public bool visible = true;

		public int layer = 1;

		public SpriteTemplate spriteTemplate;

        #region Properties
        protected double _x;
        public virtual double x
        {
            get { return _x; }
            set { _x = value; }
        }

        protected double _y;
		public virtual double y //meliot: was double but we were getting stung by crap like  5.344552E-42!=0 when clearly that was the intent
        {
            get { return _y; }
            set 
			{
				//if (this is Mario)
				//    Debug.WriteLine("setting mario Y to : " + y.ToString());
				_y = value; 
			}
        }

        protected double _xOld;
        public virtual double xOld
        {
            get { return _xOld; }
            set { _xOld = value; }
        }

        protected double _yOld;
        public virtual double yOld
        {
            get { return _yOld; }
            set { _yOld = value; }
        }

        protected double _xDelta;  //todo: need better names
        public virtual double xDelta
        {
            get { return _xDelta; }
            set { _xDelta = value; }
        }

        protected double _yDelta;  //todo: need better names
        public virtual double yDelta
        {
            get { return _yDelta; }
            set 
			{
				//if (this is Mario)
				//{
				//    //allows us to set breakpoints easily
				//    if(value>0)
				//        Debug.WriteLine("UP: setting mario Y to : " + y.ToString());
				//    else
				//        Debug.WriteLine("down: setting mario Y to : " + y.ToString());
				//}

				_yDelta = value; 
			}
        }
        #endregion

        //meliot: looks like xa is set outside the class, then this is called... not good
        //TODO: make it like move(x,y)
		public virtual void move()
		{
			x += xDelta;
			y += yDelta;
		}

		public virtual void renderFlipped(WriteableBitmap wbmp, double alpha)
		{
			if (!visible) return;

			int xToUse = (int)-x, yToUse = (int)-(y - hPic) ;

			//if (xToUse < 0 || yToUse < 0) 
			//    Debug.WriteLine("break!");


			//wbmp.drawImage(sheet[xPic, yPic],
			//    (int)x,
			//    (int)y-hPic); //meliot: this makes the sprites display at the proper coord's but since collision detection doesn't appear to work on enemies, 

			wbmp.drawImage(sheet[xPic, yPic],
				xToUse,
				yToUse); //meliot: this makes the sprites display at the proper coord's but since collision detection doesn't appear to work on enemies, 
		}



		public virtual void render(WriteableBitmap wbmp, double alpha)
		{
			if (!visible) return;

            //meliot- I just don't get this code,- not sure what the purpose is...
            /* the original code
            //int xPixel = (int)(xOld + (x - xOld) * alpha) - xPicO;
            //int yPixel = (int)(yOld + (y - yOld) * alpha) - yPicO;

            //wbmp.Invalidate();
            //wbmp.drawImage(sheet[xPic, yPic],  //meliot: this version of drawImage doesn't seem to work well...
            //    xPixel + (xFlipPic ? wPic : 0), 
            //    yPixel + (yFlipPic ? hPic : 0), 
            //    xFlipPic ? -wPic : wPic, 
            //    yFlipPic ? -hPic : hPic);
            */

            //meliot: xFlipPic and yFlipPic must get set from outside the class- bad

			int xToUse = (int)(xFlipPic ? -x : x), yToUse = (int)(yFlipPic ? -(y-hPic) : y-hPic);

			//if (xToUse < 0 || yToUse < 0) 
			//    Debug.WriteLine("break!");


			//wbmp.drawImage(sheet[xPic, yPic],
			//    (int)x,
			//    (int)y-hPic); //meliot: this makes the sprites display at the proper coord's but since collision detection doesn't appear to work on enemies, 

			wbmp.drawImage(sheet[xPic, yPic],
				xToUse,
				yToUse); //meliot: this makes the sprites display at the proper coord's but since collision detection doesn't appear to work on enemies, 
		}

		/*  private void blit(Graphics og, Image bitmap, int x0, int y0, int x1, int y1, int w, int h)
			{
				if (!xFlipPic)
				{
					if (!yFlipPic)
					{
						og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1, y1, x1+w, y1+h, null);
					}
					else
					{
						og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1, y1+h, x1+w, y1, null);
					}
				}
				else
				{
					if (!yFlipPic)
					{
						og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1+w, y1, x1, y1+h, null);
					}
					else
					{
						og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1+w, y1+h, x1, y1, null);
					}
				}
			}*/

		public virtual void tick()
		{
			if ((this is Mario || this is Enemy) && (x != xOld || y != yOld))
			{
				//Debug.WriteLine(this.GetType().ToString()+": " + x.ToString() + "," + y.ToString());
				xOld = x;
				yOld = y;
			}


			xOld = x;
			yOld = y;
			move();
		}

		public virtual void tickNoMove()
		{
			xOld = x;
			yOld = y;
		}

		public virtual double getX(double alpha)
		{
			return (xOld + (x - xOld) * alpha) - xPicO;
		}

		public virtual double getY(double alpha)
		{
			return (yOld + (y - yOld) * alpha) - yPicO;
		}

		public virtual void collideCheck()
		{
		}

		public virtual void bumpCheck(int xTile, int yTile)
		{
		}

		public virtual bool shellCollideCheck(Shell shell)
		{
			return false;
		}

		public virtual void release(Mario mario)
		{
		}

		public virtual bool fireballCollideCheck(Fireball fireball)
		{
			return false;
		}
	}
}